import com.fasterxml.jackson.databind.ObjectMapper;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.KeyStore;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.logging.Logger;

class Message{
    //    确保java代码中类/属性的名字与 json 中名字相对应
    public String from;
    public String to;
    public String message;
    public String toString() {
        return "Message{from = " + from + ", to = " + to + ", message = " + message + "}";
    }
}
@WebServlet("/message")
public class Message_Servlet extends HttpServlet {
    private MysqlDataSource dataSource;

    @Override
    public void init() throws ServletException {
        MysqlDataSource ds = new MysqlDataSource();

        // 设置数据库连接的完整URL，包括数据库的IP地址(localhost)，端口号(3306)，
// 数据库名(message_wall)，字符编码设置(charsetEncoding=utf8)和SSL连接设置(useSSL=false)。
        ds.setUrl("jdbc:mysql://localhost:3306/message_wall?charsetEncoding=utf8&useSSL=false");
        ds.setUser("root");
        ds.setPassword("123456");
        this.dataSource = ds;
    }


    //        读取前端发来的信息  把数据保存在服务器当中
   // List<Message> messageList = new ArrayList<>();//存储 前端发来的消息
    ObjectMapper objectMapper = new ObjectMapper();
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //        使用ObjectMapper从HttpServletRequest的输入流中读取JSON数据。
//        req.getInputStream()提供了请求体的原始字节流
        Message message = objectMapper.readValue(req.getInputStream(), Message.class);
//        readValue方法把JSON字符串转换成Java的Request对象。
        System.out.println("收到请求发来的消息:"+message);
//      存储消息  1.存储在内存中(重启 重连服务器则会消失)  2.数据库 持久化存储
      //  messageList.add(message);

//        插入数据库
        try {
            save(message);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

//        返回响应
        resp.setStatus(200);
        resp.setContentType("text/plain; charset=UTF-8");
        //resp.setContentType("application/json;charset=utf8");
        resp.getWriter().write(" 返回响应 OK! ");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json; charset=utf-8");
        //        通过这个方法来处理当前获取消息列表的 get请求 不需要解析参数,直接返回
        resp.setStatus(200);

//         从数据库里查询
        try {
            List<Message> messageList = load();  // 从数据库加载消息列表
            // 使用 ObjectMapper 将消息列表转换为 JSON 字符串
            String respJson = objectMapper.writeValueAsString(messageList);
            resp.getWriter().write(respJson);  // 将 JSON 数据写入响应
        } catch (SQLException e) {
            resp.getWriter().write("{\"error\":\"Unable to retrieve messages\"}");
            e.printStackTrace();
        }

//       对于 List 类型的数据,jackon可以直接将其变为 json数组
        //String respJson = objectMapper.writeValueAsString(messageList);
       // resp.getWriter().write(respJson);
    }
    private void save (Message message) throws SQLException {
//        将 message 插入到数据库中

//        1.创建数据源(使用 init() 在Servlet生命周期内复用)
//        2.建立连接
        Connection connection = dataSource.getConnection();
//        3.构造 SQL
        // 准备一个SQL语句模板，用于插入数据。问号(?)是参数的占位符，稍后将被具体的参数值替换
        String sql = "insert into message values(?,?,?)";
        PreparedStatement statement = connection.prepareStatement(sql);
        statement.setString(1,message.from);
        statement.setString(2,message.to);
        statement.setString(3,message.message);

//        4.执行 SQL
        // 执行更新操作，此方法用于执行INSERT、UPDATE或 DELETE语句。
        statement.executeLargeUpdate();
//        5.回收资源
        statement.close();
        connection.close();
    }
    private List<Message> load () throws SQLException {
       // 从数据库中读取到 message

//        1.创建数据源(使用 init() 在 Servlet 生命周期内可以复用)
//        2.构建连接
        Connection connection = dataSource.getConnection();

        //3. 准备一个 SQL 查询语句，用于从 message 表中检索所有记录
        String sql = "SELECT `from`, `to`, `message` FROM message";
        // 创建一个 PreparedStatement 对象，这个对象管理你的 SQL 命令
//        PreparedStatement 方法用于管理 sql 语句
        PreparedStatement statement = connection.prepareStatement(sql);
//        4.执行 SQL
        ResultSet resultSet = statement.executeQuery();// 执行查询，返回结果集。

//        5.遍历结果集合
        // 创建一个 List 来存储从数据库读取的 Message 对象。
        List<Message> messageList = new ArrayList<>();
        while(resultSet.next()){
            Message message = new Message();
            message.from = resultSet.getString("from");
            message.to = resultSet.getString("to");
            message.message = resultSet.getString("message");
            messageList.add(message);
        }
//        6.回收资源
        resultSet.close();
        statement.close();
        connection.close();
//        7.返回 messageList
        return messageList;
    }
}
